package myjava.l_reflect.reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @Auther: cty
 * @Date: 2020/2/19 15:50
 * @Description: 操作方法
 * 	一、获取类对象
 * 	二、获取方法对象
 * 		    getMethods()							        获取 “类及其父类” 的 “所有” 公共方法      返回Method[]
 * 		    getMethod(String name,数据类型.class,...)		获取 “类及其父类” 的 “指定” 公共方法      返回Method
 *				    String name  	    表示方法名
 * 				    数据类型.class,...  	表示方法接收的参数类型的类对象
 * 		    getDeclaredMethods()					        获取 “类” 的 “所有” 方法                 返回Method[]
 * 		    getDeclaredMethod(String name,Class...cla)	    获取 “类” 的 “指定” 方法                 返回Method
 * 	三、操作方法
 * 		    静态方法
 * 				    方法对象.invoke(null,参数值1,参数值2,....);
 * 				    方法对象.invoke(null,null);
 * 		    非静态方法
 * 				    Object obj=cla.newInstance();
 * 				    方法对象.invoke(obj,参数值1,参数值2,....)
 * 				    方法对象.invoke(obj,null)
 *
 * @version: 1.0
 */
public class OperateMethod {
    public static void main(String[] args) {
        testMethod();
    }

    // 打印方法对象的修饰符、返回值类型、方法名、形参
    public static void printInfo(Method md){
        // Method类常用方法
        System.out.println("获取修饰符-->"+md.getModifiers());  // 每个修饰符对应一个数值，若有多个修饰符则返回数值之和
        System.out.println("获取返回值类型-->"+md.getReturnType());  // 返回一个 class对象
        System.out.println("获取方法名-->"+md.getName());  // 返回一个字符串
        System.out.println("获取形参类型：");  // 返回一个class对象数组
        for(int i=0; i<md.getParameterTypes().length; i++){
            System.out.println(md.getParameterTypes()[i]);
        }
        System.out.println("-------------------------");
    }

    // 操作方法
    public static void testMethod(){
        try {
            // 一、获取类对象
            Class cla=Class.forName("com.cty.pojo.Student");

            // 二、获取方法对象
            System.out.println("2-1 获取 “类及其父类” 的 “所有” 公共方法");
            Method[] md21 = cla.getMethods();
            for(Method m:md21){
                printInfo(m);
            }
            System.out.println("**********************************************************");

            System.out.println("2-2 获取 “类及其父类” 的 “指定” 公共方法");
            Method md22 = cla.getMethod("sleep", int.class, String.class);
            printInfo(md22);
            System.out.println("**********************************************************");

            System.out.println("2-3 获取 “类” 的 “所有” 方法（无法获取父类方法，但可以通过cla.getSuperclass()定位到父类再获取方法）");
            Method[] md23 = cla.getDeclaredMethods();
            for(Method m:md23){
                printInfo(m);
            }
            System.out.println("**********************************************************");

            System.out.println("2-4 获取 “类” 的 “指定” 方法（无法获取父类方法，但可以通过cla.getSuperclass()定位到父类再获取方法）");
            Method md24 = cla.getDeclaredMethod("doExercises", String.class, int.class, int.class);
            printInfo(md24);
            System.out.println("**********************************************************");

            // 三、操作方法对象（执行方法）
            System.out.println("3-1 操作静态方法");
            Method md31 = cla.getDeclaredMethod("speak", String.class);
            md31.invoke(null, "今天学了反射，好开心！");
            System.out.println("**********************************************************");

            System.out.println("3-2 操作非静态方法");
            Method md32 = cla.getDeclaredMethod("study", String.class);
            Object obj32 = cla.newInstance();  // 获取实例对象
            md32.invoke(obj32, "不要打扰我，谢谢。");

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}


/* res:
2-1 获取 “类及其父类” 的 “所有” 公共方法
获取修饰符-->1
获取返回值类型-->void
获取方法名-->study
获取形参类型：
class java.lang.String
-------------------------
获取修饰符-->9
获取返回值类型-->void
获取方法名-->speak
获取形参类型：
class java.lang.String
-------------------------
获取修饰符-->1
获取返回值类型-->int
获取方法名-->doExercises
获取形参类型：
class java.lang.String
int
int
-------------------------
获取修饰符-->1
获取返回值类型-->void
获取方法名-->sleep
获取形参类型：
class java.lang.String
int
-------------------------
获取修饰符-->1
获取返回值类型-->void
获取方法名-->sleep
获取形参类型：
int
class java.lang.String
-------------------------
获取修饰符-->1
获取返回值类型-->void
获取方法名-->sayHello
获取形参类型：
-------------------------
获取修饰符-->273
获取返回值类型-->void
获取方法名-->wait
获取形参类型：
long
-------------------------
...
**********************************************************
2-2 获取 “类及其父类” 的 “指定” 公共方法
获取修饰符-->1
获取返回值类型-->void
获取方法名-->sleep
获取形参类型：
int
class java.lang.String
-------------------------
**********************************************************
2-3 获取 “类” 的 “所有” 方法（无法获取父类方法，但可以通过cla.getSuperclass()定位到父类再获取方法）
获取修饰符-->1
获取返回值类型-->void
获取方法名-->study
获取形参类型：
class java.lang.String
-------------------------
获取修饰符-->9
获取返回值类型-->void
获取方法名-->speak
获取形参类型：
class java.lang.String
-------------------------
获取修饰符-->1
获取返回值类型-->int
获取方法名-->doExercises
获取形参类型：
class java.lang.String
int
int
-------------------------
**********************************************************
2-4 获取 “类” 的 “指定” 方法（无法获取父类方法，但可以通过cla.getSuperclass()定位到父类再获取方法）
获取修饰符-->1
获取返回值类型-->int
获取方法名-->doExercises
获取形参类型：
class java.lang.String
int
int
-------------------------
**********************************************************
3-1 操作静态方法
今天学了反射，好开心！
**********************************************************
3-2 操作非静态方法
我在学习，不要打扰我，谢谢。
*/